1 /*
2  * Copyright (c) 2011-2014 - Mauro Carvalho Chehab
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation version 2.1 of the License.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
17  */
18 
19 module libdvbv5_d.dvb_scan;
20 
21 import libdvbv5_d.dvb_fe: dvb_v5_fe_parms;
22 import libdvbv5_d.dvb_file: dvb_entry;
23 import libdvbv5_d.dvb_v5_std: dvb_sat_polarization;
24 import libdvbv5_d.pat: dvb_table_pat_program, dvb_table_pat;
25 import libdvbv5_d.nit: dvb_table_nit;
26 import libdvbv5_d.pmt: dvb_table_pmt;
27 import libdvbv5_d.sdt: dvb_table_sdt;
28 import libdvbv5_d.vct: atsc_table_vct;
29 
30 extern (C):
31 
32 /**
33  * @file dvb-scan.h
34  * @ingroup frontend_scan
35  * @brief Provides interfaces to scan programs inside MPEG-TS digital TV streams.
36  * @copyright GNU Lesser General Public License version 2.1 (LGPLv2.1)
37  * @author Mauro Carvalho Chehab
38  *
39  * @par Bug Report
40  * Please submit bug reports and patches to linux-media@vger.kernel.org
41  */
42 
43 /* According with ISO/IEC 13818-1:2007 */
44 
45 enum MAX_TABLE_SIZE = 1024 * 1024;
46 
47 // struct dvb_entry;
48 
49 /**
50  * @struct dvb_v5_descriptors_program
51  * @brief Associates PMT with PAT tables
52  * @ingroup frontend_scan
53  *
54  * @param pat_pgm	pointer for PAT descriptor
55  * @param pmt	pointer for PMT descriptor
56  */
57 struct dvb_v5_descriptors_program
58 {
59     // struct dvb_table_pat_program;
60     dvb_table_pat_program* pat_pgm;
61     // struct dvb_table_pmt;
62     dvb_table_pmt* pmt;
63 }
64 
65 /**
66  * @struct dvb_v5_descriptors
67  * @brief Contains the descriptors needed to scan the Service ID and other relevant info at a MPEG-TS Digital TV stream
68  * @ingroup frontend_scan
69  *
70  * @param delivery_system Delivery system of the parsed MPEG-TS
71  * @param entry		struct dvb_entry pointer (see dvb-file.h)
72  * @param pat		PAT table descriptor pointer (table ID 0x00).
73  * @param vct		VCT table descriptor pointer (either table ID 0xc8,
74  * 			for TVCT or table ID 0xc9, for CVCT)
75  * @param program	PAT/PMT array associated programs found at MPEG-TS
76  * @param num_program	Number of program entries at @ref program array.
77  * @param nit		NIT table descriptor pointer for table ID 0x40.
78  * @param sdt		SDT table descriptor pointer for table ID 0x42.
79  * @param other_nits	Contains an array of pointers to the other NIT
80  *			extension tables identified by table ID 0x41.
81  * @param num_other_nits Number of NIT tables at @ref other_nits array.
82  * @param other_sdts	Contains an array of pointers to the other NIT
83  *			extension tables identified by table ID 0x46.
84  * @param num_other_sdts Number of NIT tables at @ref other_sdts array.
85  *
86  * Those descriptors are filled by the scan routines when the tables are
87  * found. Otherwise, they're NULL.
88  *
89  * @note: Never alloc this struct yourself. This is meant to always be
90  * allocated via dvb_scan_alloc_handler_table() or via dvb_get_ts_tables().
91  */
92 struct dvb_v5_descriptors
93 {
94     uint delivery_system;
95 
96     dvb_entry* entry;
97     uint num_entry;
98 
99     // struct dvb_table_pat;
100     dvb_table_pat* pat;
101     // struct atsc_table_vct;
102     atsc_table_vct* vct;
103     dvb_v5_descriptors_program* program;
104     // struct dvb_table_nit;
105     dvb_table_nit* nit;
106     // struct dvb_table_sdt;
107     dvb_table_sdt* sdt;
108 
109     uint num_program;
110 
111     dvb_table_nit** other_nits;
112     uint num_other_nits;
113 
114     dvb_table_sdt** other_sdts;
115     uint num_other_sdts;
116 }
117 
118 /**
119  * @struct dvb_table_filter
120  * @brief Describes the PES filters used by DVB scan
121  * @ingroup frontend_scan
122  *
123  * @param tid		Table ID
124  * @param pid		Program ID
125  * @param ts_id		Table section ID (for multisession filtering). If no
126  *			specific table section is needed, -1 should be used
127  * @param table		pointer to a pointer for the table struct to be filled
128  * @param allow_section_gaps	Allow non-continuous section numbering
129  * @param priv		Internal structure used inside the DVB core. shouldn't
130  *			be touched externally.
131  */
132 struct dvb_table_filter
133 {
134     /* Input data */
135     ubyte tid;
136     ushort pid;
137     int ts_id;
138     void** table;
139 
140     int allow_section_gaps;
141 
142     /*
143     	 * Private temp data used by dvb_read_sections().
144     	 * Should not be filled outside dvb-scan.c, as they'll be
145     	 * overrided
146     	 */
147     void* priv;
148 }
149 
150 /**
151  * @brief deallocates all data associated with a table filter
152  * @ingroup frontend_scan
153  *
154  * @param sect	table filter pointer
155  */
156 void dvb_table_filter_free (dvb_table_filter* sect);
157 
158 /**
159  * @brief read MPEG-TS tables that comes from a DTV card
160  * @ingroup frontend_scan
161  *
162  * @param parms		pointer to struct dvb_v5_fe_parms created when the
163  *			frontend is opened
164  * @param dmx_fd	an opened demux file descriptor
165  * @param tid		Table ID
166  * @param pid		Program ID
167  * @param table		pointer to a pointer for the table struct to be filled
168  * @param timeout	Limit, in seconds, to read a MPEG-TS table
169  *
170  * This function is used to read the DVB tables by specifying a table ID and
171  * a program ID. The libdvbv5 should have a parser for the descriptors of the
172  * table type that should be parsed.
173  * The table will be automatically allocated on success.
174  * The function will read on the specified demux and return when reading is
175  * done or an error has occurred. If table is not NULL after the call, it has
176  * to be freed with the apropriate free table function (even if an error has
177  * occurred).
178  *
179  * If the application wants to abort the read operation, it can change the
180  * value of parms->p.abort to 1.
181  *
182  * Returns 0 on success or a negative error code.
183  *
184  * Example usage:
185  * @code
186  * struct dvb_table_pat *pat;
187  * int r = dvb_read_section( parms, dmx_fd, DVB_TABLE_PAT, DVB_TABLE_PAT_PID,
188  *			    (void **) &pat, 5 );
189  * if (r < 0)
190  *	dvb_logerr("error reading PAT table");
191  * else {
192  *	// do something with pat
193  * }
194  * if (pat)
195  *	dvb_table_pat_free( pat );
196  * @endcode
197  */
198 int dvb_read_section (
199     dvb_v5_fe_parms* parms,
200     int dmx_fd,
201     ubyte tid,
202     ushort pid,
203     void** table,
204     uint timeout);
205 
206 /**
207  * @brief read MPEG-TS tables that comes from a DTV card
208  *				with an specific table section ID
209  * @ingroup frontend_scan
210  *
211  * @param parms		pointer to struct dvb_v5_fe_parms created when the
212  * 			frontend is opened
213  * @param dmx_fd	an opened demux file descriptor
214  * @param tid		Table ID
215  * @param pid		Program ID
216  * @param ts_id		Table section ID (for multisession filtering). If no
217  *			specific table section is needed, -1 should be used
218  * @param table		pointer to a pointer for the table struct to be filled
219  * @param timeout	limit, in seconds, to read a MPEG-TS table
220  *
221  * This is a variant of dvb_read_section() that also seeks for an specific
222  * table section ID given by ts_id.
223  */
224 int dvb_read_section_with_id (
225     dvb_v5_fe_parms* parms,
226     int dmx_fd,
227     ubyte tid,
228     ushort pid,
229     int ts_id,
230     void** table,
231     uint timeout);
232 
233 /**
234  * @brief read MPEG-TS tables that comes from a DTV card
235  * @ingroup frontend_scan
236  *
237  * @param parms		pointer to struct dvb_v5_fe_parms created when the
238  *			frontend is opened
239  * @param dmx_fd	an opened demux file descriptor
240  * @param sect		section filter pointer
241  * @param timeout	limit, in seconds, to read a MPEG-TS table
242  *
243  * This is a variant of dvb_read_section() that uses a struct dvb_table_filter
244  * to specify the filter to use.
245  */
246 int dvb_read_sections (
247     dvb_v5_fe_parms* parms,
248     int dmx_fd,
249     dvb_table_filter* sect,
250     uint timeout);
251 
252 /**
253  * @brief allocates a struct dvb_v5_descriptors
254  * @ingroup frontend_scan
255  *
256  * @param delivery_system	Delivery system to be used on the table
257  *
258  * At success, returns a pointer. NULL otherwise.
259  */
260 dvb_v5_descriptors* dvb_scan_alloc_handler_table (uint delivery_system);
261 
262 /**
263  * @brief frees a struct dvb_v5_descriptors
264  * @ingroup frontend_scan
265  *
266  * @param dvb_scan_handler	pointer to the struct to be freed.
267  */
268 void dvb_scan_free_handler_table (dvb_v5_descriptors* dvb_scan_handler);
269 
270 /**
271  * @brief Scans a DVB stream, looking for the tables needed to
272  *			 identify the programs inside a MPEG-TS
273  * @ingroup frontend_scan
274  *
275  * @param parms			pointer to struct dvb_v5_fe_parms created when
276  *				the frontend is opened
277  * @param dmx_fd		an opened demux file descriptor
278  * @param delivery_system	delivery system to be scanned
279  * @param other_nit		use alternate table IDs for NIT and other tables
280  * @param timeout_multiply	improves the timeout for each table reception
281  * 				by using a value that will multiply the wait
282  *				time.
283  *
284  * Given an opened frontend and demux, this function seeks for all programs
285  * available at the transport stream, and parses the following tables:
286  * PAT, PMT, NIT, SDT (and VCT, if the delivery system is ATSC).
287  *
288  * On sucess, it returns a pointer to a struct dvb_v5_descriptors, that can
289  * either be used to tune into a service or to be stored inside a file.
290  */
291 dvb_v5_descriptors* dvb_get_ts_tables (
292     dvb_v5_fe_parms* parms,
293     int dmx_fd,
294     uint delivery_system,
295     uint other_nit,
296     uint timeout_multiply);
297 
298 /**
299  * @brief frees a struct dvb_v5_descriptors
300  * @ingroup frontend_scan
301  *
302  * @param dvb_desc	pointed to the structure to be freed.
303  *
304  * This function recursively frees everything that is allocated by
305  * dvb_get_ts_tables() and stored at dvb_desc, including dvb_desc itself.
306  */
307 void dvb_free_ts_tables (dvb_v5_descriptors* dvb_desc);
308 
309 /**
310  * @brief Callback for the application to show the frontend status
311  * @ingroup frontend_scan
312  *
313  * @param args		a pointer, opaque to libdvbv5, to be used by the
314  *			application if needed.
315  * @param parms		pointer to struct dvb_v5_fe_parms created when the
316  *			frontend is opened
317  */
318 alias check_frontend_t = int function (void* args, dvb_v5_fe_parms* parms);
319 
320 /**
321  * @brief Scans a DVB dvb_add_scaned_transponder
322  * @ingroup frontend_scan
323  *
324  * @param parms		pointer to struct dvb_v5_fe_parms created when the
325  *			frontend is opened
326  * @param entry		DVB file entry that corresponds to a transponder to be
327  * 			tuned
328  * @param dmx_fd		an opened demux file descriptor
329  * @param check_frontend	a pointer to a function that will show the frontend
330  *			status while tuning into a transponder
331  * @param args		a pointer, opaque to libdvbv5, that will be used when
332  *			calling check_frontend. It should contain any parameters
333  *			that could be needed by check_frontend.
334  * @param other_nit		Use alternate table IDs for NIT and other tables
335  * @param timeout_multiply	Improves the timeout for each table reception, by
336  *
337  * This is the function that applications should use when doing a transponders
338  * scan. It does everything needed to fill the entries with DVB programs
339  * (virtual channels) and detect the PIDs associated with them.
340  *
341  * A typical usage is to after open a channel file, open a dmx_fd and open
342  * a frontend. Then, seek for the MPEG tables on all the transponder
343  * frequencies with:
344  *
345  * @code
346  * for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
347  *	struct dvb_v5_descriptors *dvb_scan_handler = NULL;
348  *
349  *	dvb_scan_handler = dvb_scan_transponder(parms, entry, dmx_fd,
350  *						&check_frontend, args,
351  *						args->other_nit,
352  *						args->timeout_multiply);
353  *	if (parms->abort) {
354  *		dvb_scan_free_handler_table(dvb_scan_handler);
355  *		break;
356  *	}
357  *	if (dvb_scan_handler) {
358  *		dvb_store_channel(&dvb_file_new, parms, dvb_scan_handler,
359  *				  args->get_detected, args->get_nit);
360  *		dvb_scan_free_handler_table(dvb_scan_handler);
361  * 	}
362  * }
363  * @endcode
364  */
365 dvb_v5_descriptors* dvb_scan_transponder (
366     dvb_v5_fe_parms* parms,
367     dvb_entry* entry,
368     int dmx_fd,
369     check_frontend_t check_frontend,
370     void* args,
371     uint other_nit,
372     uint timeout_multiply);
373 
374 /**
375  * @brief Add new transponders to a dvb_file
376  * @ingroup frontend_scan
377  *
378  * @param parms		pointer to struct dvb_v5_fe_parms created when the
379  *			frontend is opened
380  * @param dvb_scan_handler	pointer to a struct dvb_v5_descriptors containing
381  *			scaned MPEG-TS
382  * @param first_entry	first entry of a DVB file struct
383  * @param entry		current entry on a DVB file struct
384  *
385  * When the NIT table is parsed, some new transponders could be described
386  * inside. This function adds new entries to a dvb_file struct, pointing
387  * to those new transponders. It is used inside the scan loop, as shown at
388  * the dvb_scan_transponder(), to add new channels.
389  *
390  * Example:
391  * @code
392  * for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
393  *	struct dvb_v5_descriptors *dvb_scan_handler = NULL;
394  *
395  *	dvb_scan_handler = dvb_scan_transponder(parms, entry, dmx_fd,
396  *						&check_frontend, args,
397  *						args->other_nit,
398  *						args->timeout_multiply);
399  *	if (parms->abort) {
400  *		dvb_scan_free_handler_table(dvb_scan_handler);
401  *		break;
402  *	}
403  *	if (dvb_scan_handler) {
404  *		dvb_store_channel(&dvb_file_new, parms, dvb_scan_handler,
405  *				  args->get_detected, args->get_nit);
406  *		dvb_scan_free_handler_table(dvb_scan_handler);
407  *
408  *		dvb_add_scaned_transponders(parms, dvb_scan_handler,
409  *					    dvb_file->first_entry, entry);
410  *
411  *		dvb_scan_free_handler_table(dvb_scan_handler);
412  * 	}
413  * }
414  * @endcode
415  */
416 void dvb_add_scaned_transponders (
417     dvb_v5_fe_parms* parms,
418     dvb_v5_descriptors* dvb_scan_handler,
419     dvb_entry* first_entry,
420     dvb_entry* entry);
421 
422 /*
423  * Some ancillary functions used internally inside the library, used to
424  * identify duplicated transport streams and add new found transponder entries
425  */
426 int dvb_estimate_freq_shift (dvb_v5_fe_parms* parms);
427 
428 int dvb_new_freq_is_needed (
429     dvb_entry* entry,
430     dvb_entry* last_entry,
431     uint freq,
432     dvb_sat_polarization pol,
433     int shift);
434 
435 dvb_entry* dvb_scan_add_entry (
436     dvb_v5_fe_parms* parms,
437     dvb_entry* first_entry,
438     dvb_entry* entry,
439     uint freq,
440     uint shift,
441     dvb_sat_polarization pol);
442 
443 int dvb_new_entry_is_needed (
444     dvb_entry* entry,
445     dvb_entry* last_entry,
446     uint freq,
447     int shift,
448     dvb_sat_polarization pol,
449     uint stream_id);
450 
451 dvb_entry* dvb_scan_add_entry_ex (
452     dvb_v5_fe_parms* parms,
453     dvb_entry* first_entry,
454     dvb_entry* entry,
455     uint freq,
456     uint shift,
457     dvb_sat_polarization pol,
458     uint stream_id);
459 
460 void dvb_update_transponders (
461     dvb_v5_fe_parms* parms,
462     dvb_v5_descriptors* dvb_scan_handler,
463     dvb_entry* first_entry,
464     dvb_entry* entry);